/**
 * @file
 * @author dousha
 * @date 2020
 */

#ifndef TASKMAN_H
#define TASKMAN_H

#include "stdint.h"
#include "../../boilerplate/types.h"

/**
 * @defgroup ExceptionReturns 从中断中返回值
 * 
 * LR 寄存器内存储相应的值，则可以控制从中断中返回时的权限级别、协处理器和栈指针。
 */

/**
 * @defgroup TaskFlags 任务标志
 * 
 * 控制任务调度的标志。
 */

/**
 * @ingroup ExceptionReturns
 * 
 * 不使用协处理器、使用主栈、特权模式。
 */
#define EXCEPTION_RETURN_MSP_NO_FP_PRIVILEGED 0xFFFFFFF1u
/**
 * @ingroup ExceptionReturns
 * 
 * 不使用协处理器、使用主栈、线程模式。
 */
#define EXCEPTION_RETURN_MSP_NO_FP 0xFFFFFFF9u
/**
 * @ingroup ExceptionReturns
 * 
 * 不使用协处理器、使用任务栈、线程模式。
 */
#define EXCEPTION_RETURN_PSP_NO_FP 0xFFFFFFFDu
/**
 * @ingroup ExceptionReturns
 * 
 * 使用协处理器、使用主栈、特权模式。
 */
#define EXCEPTION_RETURN_MSP_FP_PRIVILEGED 0xFFFFFFE1u
/**
 * @ingroup ExceptionReturns
 * 
 * 使用协处理器、使用主栈、线程模式。
 */
#define EXCEPTION_RETURN_MSP_FP 0xFFFFFFE9u
/**
 * @ingroup ExceptionReturns
 * 
 * 使用协处理器、使用任务栈、线程模式。
 */
#define EXCEPTION_RETURN_PSP_FP 0xFFFFFFEDu

extern void *_tcb_start;

typedef uint32_t ProcessId;

typedef Result (*TaskPointer)(void);

/**
 * @ingroup TaskFlags
 * 
 * 任务需要按周期运行。
 */
#define TASK_PERIODIC 0x01u
/**
 * @ingroup TaskFlags
 * 
 * 任务不退出。即使任务返回或者调用 terminate().
 * 
 * 当任务退出时，自动重启任务。
 */
#define TASK_PERSISTENT 0x02u
/**
 * @ingroup TaskFlags
 * 
 * 任务需要在特权模式内运行。
 * 
 * @notImplemented
 */
#define TASK_PRIVILEGED 0x04u

/**
 * 任务状态
 */
typedef enum {
	/// 已创建
	TASK_CREATED,
	/// 已就绪（等待运行）
	TASK_READY,
	/// 运行中
	TASK_RUNNING,
	/// 等待延时操作
	TASK_TIMED_WAITING,
	/// 等待 IO 操作
	TASK_IO_WAITING,
	/// 已停止
	TASK_TERMINATED,
} TaskState;

/**
 * 任务控制块
 * 
 * 包含更底层的调度信息。
 */
typedef struct {
	/// 栈指针
	volatile void* sp;
	/// 函数头指针
	TaskPointer pc;
	/// 栈底指针
	volatile void* bp;
	/// 任务编号
	ProcessId tid;
	/// 任务标志位，见 TaskFlag
	uint8_t flags;
	/// 任务状态，见 TaskState
	TaskState state;
	/// 时间片长度
	uint8_t time;
	/// 任务谦让度，越大优先级越低
	uint8_t niceness;
} TaskControlBlock;

/**
 * 任务调度描述子
 * 
 * 指示任务何时调入。
 */
typedef struct TaskSchedule {
	/// 启动周期
	uint32_t executionDecade;
	/// 启动时间
	uint32_t executionTime;
	/// 任务
	TaskControlBlock *task;
	/// 下一个任务
	struct TaskSchedule *next;
} TaskSchedule;

/**
 * 任务管理器
 */
typedef struct {
	/// 用户任务总数
	uint32_t totalTasks;
	/// 时间片长度
	uint8_t sliceLength;
	/// 全部任务
	TaskSchedule *schedules;
	/// 当前任务
	TaskSchedule *currentSchedule;
	/// 尾部任务
	TaskSchedule *tailSchedule;
} TaskManager;

extern TaskControlBlock *currentTask;

extern void task_init();

extern void task_switch();

extern Result task_need_switching();

extern ProcessId task_spawn(TaskPointer, uint8_t);

extern void task_reschedule_current_task();

extern void task_kill(ProcessId);

extern void task_mark_switch();

extern void task_pend_switch();

extern void task_tick();

extern void task_cleanup();

extern void task_reschedule(uint32_t, uint32_t);

extern void task_mark_io_wait();

extern void task_mark_timed_wait();

#endif
